/*
 * testParser.c
 *
 *  Created on: Dec 12, 2012
 *      Author: afretign
 */

#include <string.h>
#include "processParser.h"
#include "workflow_struct.h"
#include <libxml/parser.h>
#include <ctype.h>
#ifndef NULL
#define NULL   ((void *) 0)
#endif
static xmlSAXHandler handler;

//1= niveau 1
//2=niveau 2
//.....
struct process * process = NULL;
char * elemCourant = NULL;
char * elemCourantSup = NULL;
int taille = 0;
char * buf=NULL;

//Renvoie les indices de début et de fin de chaine pour supprimer les espaces inutiles
int trim(int * debut,int * fin,char * chaine,int size){
	int i=0;
	while (isspace(chaine[i])&& i<size){
		i++;
	}
	*debut=i;
	i=size-1;
	while (i>=0 &&isspace(chaine[i])){
		i--;
	}
	*fin=i;
	return i;
}

void caracteres(void *user_data, const xmlChar *text, int length) {
	//printf("caracteres(taille:%d):text:%s:\n",length,(char *)text);
	buf=realloc(buf,(length+taille)*sizeof(char));
	bzero(buf+taille,length);
	memcpy(buf+taille, text, length);
	taille+=length;

}

void fin_element(void *user_data, const xmlChar *name) {
	if (buf==NULL){
		return;
	}
	int debut;
	int fin;
	if (trim(&debut,&fin,buf,taille)<0){
		free(buf);
		buf=NULL;
		taille = 0;
		return;
	}
	if (strcmp(elemCourant, "tns:description") == 0) {
		if (strcmp(elemCourantSup, "tns:process") == 0) {
			process->description = malloc((fin-debut+2) * sizeof(char));
			bzero(process->description,(fin-debut+2)*sizeof(char));
			memcpy(process->description, buf+debut, (fin-debut+1) * sizeof(char));
#ifdef VERBOSE
		printf("description:%s \n", process->description);
#endif
		}
		if (strcmp(elemCourantSup, "tns:activity") == 0) {
			process->activities[process->nbActivities - 1].description = malloc(
					(fin-debut+2) * sizeof(char));
			bzero(process->activities[process->nbActivities - 1].description,(fin-debut+2)*sizeof(char));
			memcpy(process->activities[process->nbActivities - 1].description,
					buf+debut, (fin-debut+1) * sizeof(char));
#ifdef VERBOSE
		printf("description:%s \n", process->activities[process->nbActivities - 1].description);
#endif
		}
	}
	if (strcmp(elemCourant, "tns:performer") == 0) {
		process->activities[process->nbActivities - 1].performer = malloc(
				(fin-debut+2) * sizeof(char));
		bzero(process->activities[process->nbActivities - 1].performer,(fin-debut+2)*sizeof(char));
		memcpy(process->activities[process->nbActivities - 1].performer, buf+debut,
				(fin-debut+1) * sizeof(char));
#ifdef VERBOSE
		printf("performer:%s\n",process->activities[process->nbActivities - 1].performer);
#endif
	}
	free(buf);
	buf=NULL;
	taille = 0;
}

void debut_element(void *user_data, const xmlChar *name, const xmlChar **attrs) {
	if (elemCourant != NULL) {
		elemCourantSup = elemCourant;
	}
	const char * name2=(const char *)name;
	elemCourant = malloc(strlen(name2)+1 * sizeof(char));
	bzero(elemCourant,strlen(name2)+1);
	memcpy(elemCourant, name2, strlen(name2));
	if (strcmp("tns:variableList", name2) == 0) {
		process->nbVariables = 0;
		process->variables = NULL;
	}
	if (strcmp("tns:activityList", name2) == 0) {
		process->nbActivities = 0;
		process->activities = NULL;
	}
	if (strcmp("tns:transitionList", name2) == 0) {
		process->nbTransitions = 0;
		process->transitions = NULL;
	}
	if (strcmp("tns:process", name2) == 0) {
		process = malloc(sizeof(struct process));
		process->state=RUNNING;
	}
	if (strcmp("tns:condition", name2) == 0) {
		process->transitions[process->nbTransitions - 1].condition = malloc(
				strlen((const char *)attrs[1]) + 1);
		bzero(process->transitions[process->nbTransitions - 1].condition,
				strlen((const char *)attrs[1]) + 1);
		memcpy(process->transitions[process->nbTransitions - 1].condition,
				(const char *)attrs[1], strlen((const char *)attrs[1]));
#ifdef VERBOSE
		printf("condition:%s\n",process->transitions[process->nbTransitions-1].condition );
#endif
	}
	if (strcmp("tns:variable", name2) == 0) {
#ifdef VERBOSE
		printf("variable:\n");
#endif
		process->nbVariables++;
		process->variables = realloc(process->variables, process->nbVariables
				* sizeof(struct variable));
		process->variables[process->nbVariables - 1].name = malloc(strlen(
				(const char *)attrs[1]) + 1);
		bzero(process->variables[process->nbVariables - 1].name, strlen(
				(const char *)attrs[1]) + 1);
		memcpy(process->variables[process->nbVariables - 1].name, (const char *)attrs[1],
				strlen((const char *)attrs[1]));

#ifdef VERBOSE
		printf("nom:%s\n",process->variables[process->nbVariables-1].name );
#endif
		process->variables[process->nbVariables - 1].type = malloc(strlen(
				(const char *)attrs[3]) + 1);
		bzero(process->variables[process->nbVariables - 1].type, strlen(
				(const char *)attrs[3]) + 1);
		memcpy(process->variables[process->nbVariables - 1].type, (const char *)attrs[3],
				strlen((const char *)attrs[3]));
#ifdef VERBOSE
		printf("type:%s\n",process->variables[process->nbVariables-1].type );
#endif
		if ((const char *)attrs[4] != NULL) {
			process->variables[process->nbVariables - 1].value = malloc(
					strlen((const char *)attrs[5]) + 1);
			bzero(process->variables[process->nbVariables - 1].value,
					strlen((const char *)attrs[5]) + 1);
			memcpy(process->variables[process->nbVariables - 1].value,
					(const char *)attrs[5], strlen((const char *)attrs[5]));
#ifdef VERBOSE
			printf("initiale:%s\n",process->variables[process->nbVariables-1].value );
#endif
		}
		else{
			process->variables[process->nbVariables - 1].value = NULL;
		}
	}
	if (strcmp("tns:input", name2) == 0) {
		process->activities[process->nbActivities - 1].nbInput++;
		process->activities[process->nbActivities - 1].input = realloc(
				process->activities[process->nbActivities - 1].input,
				process->activities[process->nbActivities - 1].nbInput
						* sizeof(char *));

		process->activities[process->nbActivities - 1].input[process->activities[process->nbActivities
				- 1].nbInput - 1] = malloc(strlen((const char *)attrs[1] )+1);
		bzero(
				process->activities[process->nbActivities - 1].input[process->activities[process->nbActivities
						- 1].nbInput - 1], strlen((const char *)attrs[1]) + 1);
		memcpy(
				process->activities[process->nbActivities - 1].input[process->activities[process->nbActivities
						- 1].nbInput - 1], (const char *)attrs[1], strlen((const char *)attrs[1]));
#ifdef VERBOSE
		printf("input:%s\n",process->activities[process->nbActivities-1].input[process->activities[process->nbActivities-1].nbInput-1]);
#endif
	}
	if (strcmp("tns:output", name2) == 0) {
		process->activities[process->nbActivities - 1].nbOutput++;
		process->activities[process->nbActivities - 1].output = realloc(
				process->activities[process->nbActivities - 1].output,
				process->activities[process->nbActivities - 1].nbOutput
						* sizeof(char *));

		process->activities[process->nbActivities - 1].output[process->activities[process->nbActivities
				- 1].nbOutput - 1] = malloc(strlen((const char *)attrs[1] ) + 1);
		bzero(
				process->activities[process->nbActivities - 1].output[process->activities[process->nbActivities
						- 1].nbOutput - 1], strlen((const char *)attrs[1]) + 1);
		memcpy(
				process->activities[process->nbActivities - 1].output[process->activities[process->nbActivities
						- 1].nbOutput - 1], (const char *)attrs[1], strlen((const char *)attrs[1]));
#ifdef VERBOSE
		printf("output:%s\n",process->activities[process->nbActivities-1].output[process->activities[process->nbActivities-1].nbOutput-1]);
#endif
	}
	if (strcmp("tns:activity", name2) == 0) {
#ifdef VERBOSE
		printf("activite:%s\n",name2);
#endif
		process->nbActivities++;
		process->activities = realloc(process->activities,
				process->nbActivities * sizeof(struct activity));
		process->activities[process->nbActivities - 1].nbOutput = 0;
		process->activities[process->nbActivities - 1].nbInput = 0;
		process->activities[process->nbActivities - 1].input = NULL;
		process->activities[process->nbActivities - 1].output = NULL;
		if (process->nbActivities - 1==0){
			process->activities[process->nbActivities - 1].state=RUNNING;
		}
		else{
			process->activities[process->nbActivities - 1].state=NOT_STARTED;
		}
		//processID
		int tab[2];
		if (strcmp((const char *)attrs[0],"id")==0){
			tab[0]=1;
			tab[1]=3;
		}
		else{
			tab[0]=3;
			tab[1]=1;
		}
		process->activities[process->nbActivities - 1].id = malloc(strlen(
				(const char *)attrs[tab[0]]) + 1);
		bzero(process->activities[process->nbActivities - 1].id, strlen(
				(const char *)attrs[tab[0]]) + 1);
		memcpy(process->activities[process->nbActivities - 1].id, (const char *)attrs[tab[0]],
				strlen((const char *)attrs[tab[0]]));
#ifdef VERBOSE
		printf("id:%s\n",process->activities[process->nbActivities-1].id);
#endif
		//processname2
		process->activities[process->nbActivities - 1].name = malloc(strlen(
				(const char *)attrs[tab[1]]) + 1);
		bzero(process->activities[process->nbActivities - 1].name, strlen(
				(const char *)attrs[tab[1]]) + 1);
		memcpy(process->activities[process->nbActivities - 1].name, (const char *)attrs[tab[1]],
				strlen((const char *)attrs[tab[1]]));
#ifdef VERBOSE
		printf("name2:%s\n",process->activities[process->nbActivities-1].name);
#endif
	}
	if (strcmp("tns:transition", name2) == 0) {
#ifdef VERBOSE
		printf("transition:\n");
#endif
		int tab[3];
		int i;
		//Emplacements dans attrs de chaque attribut(ordre peut changer)
		for (i=0;i<=5;i+=2){
			if (strcmp("id",(const char *)attrs[i])==0){
				tab[0]=i+1;
			}
			if (strcmp("from",(const char *)attrs[i])==0){
				tab[1]=i+1;
			}
			if (strcmp("to",(const char *)attrs[i])==0){
				tab[2]=i+1;
			}
		}
		process->nbTransitions++;
		process->transitions = realloc(process->transitions,
				process->nbTransitions * sizeof(struct transition));
		process->transitions[process->nbTransitions - 1].id = malloc(strlen(
				(const char *)attrs[tab[0]]) + 1);
		bzero(process->transitions[process->nbTransitions - 1].id, strlen(
				(const char *)attrs[tab[0]]) + 1);
		memcpy(process->transitions[process->nbTransitions - 1].id, (const char *)attrs[tab[0]],
				strlen((const char *)attrs[tab[0]]));
#ifdef VERBOSE
		printf("id:%s\n",process->transitions[process->nbTransitions-1].id);
#endif
		process->transitions[process->nbTransitions - 1].from = malloc(strlen(
				(const char *)attrs[tab[1]]) + 1);
		bzero(process->transitions[process->nbTransitions - 1].from, strlen(
				(const char *)attrs[tab[1]]) + 1);
		memcpy(process->transitions[process->nbTransitions - 1].from, (const char *)attrs[tab[1]],
				strlen((const char *)attrs[tab[1]]));
#ifdef VERBOSE
		printf("from:%s\n",process->transitions[process->nbTransitions-1].from);
#endif
		process->transitions[process->nbTransitions - 1].to = malloc(strlen(
				(const char *)attrs[tab[2]]) + 1);
		bzero(process->transitions[process->nbTransitions - 1].to, strlen(
				(const char *)attrs[tab[2]]) + 1);
		memcpy(process->transitions[process->nbTransitions - 1].to, (const char *)attrs[tab[2]],
				strlen((const char *)attrs[tab[2]]));
#ifdef VERBOSE
		printf("to:%s\n",process->transitions[process->nbTransitions-1].to);
#endif
		process->transitions[process->nbTransitions - 1].condition=NULL;
	}

}

struct process * parse(char * file) {
	handler.startElement = debut_element;
	handler.endElement = fin_element;
	handler.characters = caracteres;

	if (xmlSAXUserParseFile(&handler, NULL, file) < 0) {
		perror("oups parser");
		return NULL;
	}

	return process;
}
/*int main() {
	parse("../Models/process1.xml");
}*/
